home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / net / res_mkquery.c < prev    next >
C/C++ Source or Header  |  1988-07-29  |  6KB  |  204 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #if defined(LIBC_SCCS) && !defined(lint)
  14. static char sccsid[] = "@(#)res_mkquery.c    6.7 (Berkeley) 3/7/88";
  15. #endif /* LIBC_SCCS and not lint */
  16.  
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <netinet/in.h>
  20. #include <arpa/nameser.h>
  21. #include <resolv.h>
  22.  
  23. /*
  24.  * Form all types of queries.
  25.  * Returns the size of the result or -1.
  26.  */
  27.     /* ARGSUSED */
  28. res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
  29.     int op;            /* opcode of query */
  30.     char *dname;        /* domain name */
  31.     int class, type;    /* class and type of query */
  32.     char *data;        /* resource record data */
  33.     int datalen;        /* length of data */
  34.     struct rrec *newrr;    /* new rr for modify or append */
  35.     char *buf;        /* buffer to put query */
  36.     int buflen;        /* size of buffer */
  37. {
  38.     register HEADER *hp;
  39.     register char *cp;
  40.     register int n;
  41.     char dnbuf[MAXDNAME];
  42.     char *dnptrs[10], **dpp, **lastdnptr;
  43.     extern char *index();
  44.  
  45. #ifdef DEBUG
  46.     if (_res.options & RES_DEBUG)
  47.         printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
  48. #endif DEBUG
  49.     /*
  50.      * Initialize header fields.
  51.      */
  52.     hp = (HEADER *) buf;
  53.     hp->id = htons(++_res.id);
  54.     hp->opcode = op;
  55.     hp->qr = hp->aa = hp->tc = hp->ra = 0;
  56.     hp->pr = (_res.options & RES_PRIMARY) != 0;
  57.     hp->rd = (_res.options & RES_RECURSE) != 0;
  58.     hp->rcode = NOERROR;
  59.     hp->qdcount = 0;
  60.     hp->ancount = 0;
  61.     hp->nscount = 0;
  62.     hp->arcount = 0;
  63.     cp = buf + sizeof(HEADER);
  64.     buflen -= sizeof(HEADER);
  65.     dpp = dnptrs;
  66.     *dpp++ = buf;
  67.     *dpp++ = NULL;
  68.     lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
  69.     /*
  70.      * If the domain name contains no dots (single label), then
  71.      * append the default domain name to the one given.
  72.      */
  73.     if ((_res.options & RES_DEFNAMES) && dname != 0 && dname[0] != '\0' &&
  74.         index(dname, '.') == NULL) {
  75.         if (!(_res.options & RES_INIT))
  76.             if (res_init() == -1)
  77.                 return(-1);
  78.         if (_res.defdname[0] != '\0') {
  79.             (void)sprintf(dnbuf, "%s.%s", dname, _res.defdname);
  80.             dname = dnbuf;
  81.         }
  82.     }
  83.     /*
  84.      * perform opcode specific processing
  85.      */
  86.     switch (op) {
  87.     case QUERY:
  88.         buflen -= QFIXEDSZ;
  89.         if ((n = dn_comp((u_char *) dname, (u_char *) cp, buflen,
  90.             (u_char **) dnptrs, (u_char **) lastdnptr)) < 0)
  91.             return (-1);
  92.         cp += n;
  93.         buflen -= n;
  94.         putshort((u_short) type, (u_char *) cp);
  95.         cp += sizeof(u_short);
  96.         putshort((u_short) class, (u_char *) cp);
  97.         cp += sizeof(u_short);
  98.         hp->qdcount = htons(1);
  99.         if (op == QUERY || data == NULL)
  100.             break;
  101.         /*
  102.          * Make an additional record for completion domain.
  103.          */
  104.         buflen -= RRFIXEDSZ;
  105.         if ((n = dn_comp((u_char *) data, (u_char *) cp, buflen,
  106.             (u_char **) dnptrs, (u_char **) lastdnptr)) < 0)
  107.             return (-1);
  108.         cp += n;
  109.         buflen -= n;
  110.         putshort(T_NULL, (u_char *) cp);
  111.         cp += sizeof(u_short);
  112.         putshort((u_short) class, (u_char *) cp);
  113.         cp += sizeof(u_short);
  114.         putlong((u_long) 0, (u_char *) cp);
  115.         cp += sizeof(u_long);
  116.         putshort((u_short) 0, (u_char *) cp);
  117.         cp += sizeof(u_short);
  118.         hp->arcount = htons(1);
  119.         break;
  120.  
  121.     case IQUERY:
  122.         /*
  123.          * Initialize answer section
  124.          */
  125.         if (buflen < 1 + RRFIXEDSZ + datalen)
  126.             return (-1);
  127.         *cp++ = '\0';    /* no domain name */
  128.         putshort((u_short) type, (u_char *) cp);
  129.         cp += sizeof(u_short);
  130.         putshort((u_short) class, (u_char *) cp);
  131.         cp += sizeof(u_short);
  132.         putlong((u_long) 0, (u_char *) cp);
  133.         cp += sizeof(u_long);
  134.         putshort((u_short) datalen, (u_char *) cp);
  135.         cp += sizeof(u_short);
  136.         if (datalen) {
  137.             bcopy(data, cp, datalen);
  138.             cp += datalen;
  139.         }
  140.         hp->ancount = htons(1);
  141.         break;
  142.  
  143. #ifdef ALLOW_UPDATES
  144.     /*
  145.      * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
  146.      * (Record to be modified is followed by its replacement in msg.)
  147.      */
  148.     case UPDATEM:
  149.     case UPDATEMA:
  150.  
  151.     case UPDATED:
  152.         /*
  153.          * The res code for UPDATED and UPDATEDA is the same; user
  154.          * calls them differently: specifies data for UPDATED; server
  155.          * ignores data if specified for UPDATEDA.
  156.          */
  157.     case UPDATEDA:
  158.         buflen -= RRFIXEDSZ + datalen;
  159.         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  160.             return (-1);
  161.         cp += n;
  162.         putshort(type, cp);
  163.                 cp += sizeof(u_short);
  164.                 putshort(class, cp);
  165.                 cp += sizeof(u_short);
  166.         putlong(0, cp);
  167.         cp += sizeof(u_long);
  168.         putshort(datalen, cp);
  169.                 cp += sizeof(u_short);
  170.         if (datalen) {
  171.             bcopy(data, cp, datalen);
  172.             cp += datalen;
  173.         }
  174.         if ( (op == UPDATED) || (op == UPDATEDA) ) {
  175.             hp->ancount = htons(0);
  176.             break;
  177.         }
  178.         /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
  179.  
  180.     case UPDATEA:    /* Add new resource record */
  181.         buflen -= RRFIXEDSZ + datalen;
  182.         if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
  183.             return (-1);
  184.         cp += n;
  185.         putshort(newrr->r_type, cp);
  186.                 cp += sizeof(u_short);
  187.                 putshort(newrr->r_class, cp);
  188.                 cp += sizeof(u_short);
  189.         putlong(0, cp);
  190.         cp += sizeof(u_long);
  191.         putshort(newrr->r_size, cp);
  192.                 cp += sizeof(u_short);
  193.         if (newrr->r_size) {
  194.             bcopy(newrr->r_data, cp, newrr->r_size);
  195.             cp += newrr->r_size;
  196.         }
  197.         hp->ancount = htons(0);
  198.         break;
  199.  
  200. #endif ALLOW_UPDATES
  201.     }
  202.     return (cp - buf);
  203. }
  204.